import os
import zipfile
import shutil

from django.http import HttpResponse, FileResponse
from django.http import Http404, StreamingHttpResponse
from django.views.generic import View
from kombu.utils import json
from nameko.standalone.rpc import ClusterRpcProxy

from config import Config, NamekoConfig
from utils import dbutil, Utils
from .task import inference as infer, train


class Dataset(View):
    def post(self, request, *args, **kwargs):
        """
        数据集上传
        :param request:
        :param args:
        :param kwargs:
        :return:
        """
        # 数据集上传保存解压
        # 解析url
        user_id = request.GET.get('user_id')
        file = request.FILES

        if not file:
            response = {
                'msg': "数据集为空",
                'status': 403,
            }
            return HttpResponse(json.dumps(response))

        zip_file_name = file['file']._get_name()
        file = file.getlist('file')[0]
        file_name = "".join(zip_file_name.split(".")[:-1])
        file_type = zip_file_name.split(".")[-1]

        # 设置数据集保存路径
        dataset_path = Config.dataset_file_path.replace('user_id',user_id)  # 指定用户的所有dataset的保存路径
        if not os.path.exists(dataset_path):
            os.makedirs(dataset_path)        # 多层创建目录
        dataset_zip_path = os.path.join(dataset_path, zip_file_name)  # 压缩包路径
        dataset_file_path = os.path.join(dataset_path,file_name)  # 数据集文件夹路径

        if file_type!= 'zip':
            msg = '数据集类型非zip'
            status = 403
        elif os.path.exists(dataset_file_path):
            msg = '数据集已存在'
            status = 403
        else:
            # 保存上传的数据集压缩包
            with open(dataset_zip_path, 'wb+') as destination:
                for chunk in file.chunks():
                    destination.write(chunk)

            # 解压到指定路径的同名文件夹下
            with zipfile.ZipFile(dataset_zip_path, 'r') as zf:
                zf.extractall(dataset_path)
            # 删除原压缩包
            os.remove(dataset_zip_path)

            # 调用微服务
            nameko_config = NamekoConfig.nameko_config
            with ClusterRpcProxy(nameko_config) as cluster_rpc:
                status = cluster_rpc.data_management.upload_dataset(user_id,file_name)
            if status==200:
                msg = '数据集上传成功'
            else:
                msg = '数据集上传失败'
                shutil.rmtree(dataset_file_path)   # 删除文件夹，无论里面是否有文件或文件夹

        response = {
            'msg': msg,
            'status': status,
        }
        return HttpResponse(json.dumps(response))

    def get(self, request, *args, **kwargs):
        """
        根据用户id和数据集名字,获取数据集信息。
        :param request:
        :param args:
        :param kwargs:
        :return:
        """
        user_id = request.GET.get('user_id')
        dataset_name = request.GET.get('dataset_name')

        # 调用微服务
        nameko_config = NamekoConfig.nameko_config
        with ClusterRpcProxy(nameko_config) as cluster_rpc:
            response = cluster_rpc.data_management.get_dataset(user_id,dataset_name)
        response = json.loads(response)
        return HttpResponse(json.dumps(response))


    def delete(self, request, *args, **kwargs):
        """
        根据用户id和数据集名字，删除数据集
        :param request:
        :param args:
        :param kwargs:
        :return:
        """
        user_id = request.GET.get('user_id')
        dataset_name = request.GET.get('dataset_name')

        # 调用微服务
        nameko_config = NamekoConfig.nameko_config
        with ClusterRpcProxy(nameko_config) as cluster_rpc:
            response = cluster_rpc.data_management.del_dataset(user_id,dataset_name)
        response = json.loads(response)
        return HttpResponse(json.dumps(response))


class DatasetList(View):
    def get(self, request, *args, **kwargs):
        """
        获取指定用户的所有数据集信息
        :param request:
        :param args:
        :param kwargs:
        :return:
        """
        user_id = request.GET.get('user_id')
        # 调用微服务
        nameko_config = NamekoConfig.nameko_config
        with ClusterRpcProxy(nameko_config) as cluster_rpc:
            response = cluster_rpc.data_management.get_dataset_list(user_id)

        response = json.loads(response)

        return HttpResponse(json.dumps(response))


class Model(View):
    def post(self, request, *args, **kwargs):
        # 创建模型
        user_id = request.GET.get('user_id')
        model_name = request.GET.get('model_name')
        # 调用微服务
        nameko_config = NamekoConfig.nameko_config
        with ClusterRpcProxy(nameko_config) as cluster_rpc:
            response = cluster_rpc.model_management.create_model(user_id,model_name)
        return HttpResponse(json.dumps(response))

    def get(self, request, *args, **kwargs):
        """
        获取模型信息
        :param request:
        :param args:
        :param kwargs:
        :return:
        """
        user_id = request.GET.get('user_id')
        model_name = request.GET.get('model_name')

        # 调用微服务
        nameko_config = NamekoConfig.nameko_config
        with ClusterRpcProxy(nameko_config) as cluster_rpc:
            response = cluster_rpc.model_management.get_model(user_id,model_name)
        response = json.loads(response)

        return HttpResponse(json.dumps(response))

    def delete(self, request, *args, **kwargs):
        """
        删除模型
        :param request:
        :param args:
        :param kwargs:
        :return:
        """
        user_id = request.GET.get('user_id')
        model_name = request.GET.get('model_name')

        # 调用微服务
        nameko_config = NamekoConfig.nameko_config
        with ClusterRpcProxy(nameko_config) as cluster_rpc:
            response = cluster_rpc.model_management.del_model(user_id,model_name)
            response = json.loads(response)
        return HttpResponse(json.dumps(response))


class ModelList(View):
    def get(self, request, *args, **kwargs):
        user_id = request.GET.get('user_id')
        # 调用微服务
        nameko_config = NamekoConfig.nameko_config
        with ClusterRpcProxy(nameko_config) as cluster_rpc:
            response = cluster_rpc.model_management.get_model_list(user_id)

        response = json.loads(response)
        return HttpResponse(json.dumps(response))


class Train(View):
    def get(self, request, *args, **kwargs):
        """
        训练模型
        :param request:
        :return:
        """
        user_id = request.GET.get('user_id')
        model_name = request.GET.get('model_name')
        dataset_name = request.GET.get('dataset_name')
        batch_size = request.GET.get('batch_size')
        learning_rate = request.GET.get('learning_rate')

        # 调用celery进行异步
        # train.delay(model_name, dataset_name)
        # 调用微服务
        nameko_config = NamekoConfig.nameko_config
        with ClusterRpcProxy(nameko_config) as cluster_rpc:
            response = cluster_rpc.model_train.train(user_id, model_name, dataset_name, batch_size, learning_rate)
        response = json.loads(response)

        return HttpResponse(json.dumps(response))


class Logs(View):
    def get(self, request, *args, **kwargs):
        user_id = request.GET.get('user_id')
        model_name = request.GET.get('model_name')
        if (not user_id or not model_name):
            return HttpResponse('下载错误，请检查命令')
        else:
            try:
                sql = """
                    select train_log_path from app_model
                    where user_id='{}' and model_name='{}'
                """.format(user_id, model_name)
                result = dbutil.query(sql)
                if not result:
                    response = {
                        'msg': '模型不存在',
                        'status': 404
                    }
                    return HttpResponse(json.dumps(response))
                else:
                    log_path = result[0][0]
                    print(log_path)
                    if not log_path:
                        response = {
                            'msg': '日志不存在',
                            'status': 404
                        }
                        return HttpResponse(json.dumps(response))
                    else:
                        file_name = os.path.basename(log_path)
                        f = open(log_path, 'rb')
                        response = FileResponse(f)  # 文件流类型
                        response['Content-Disposition'] = 'attachment; filename={}'.format(file_name)  # 表示带有文件附件，指定了文件名；浏览器会自动下载
                        return response
            except:
                response = {
                    'msg': '程序执行出错',
                    'status': 500
                }
                return HttpResponse(json.dumps(response))


class Download(View):
    def get(self, request, *args, **kwargs):
        user_id = request.GET.get('user_id')
        dataset_name = request.GET.get('dataset_name')
        model_name = request.GET.get('model_name')
        if (dataset_name is not None and model_name is not None) \
                or (dataset_name is None and model_name is None):
            return HttpResponse('下载错误，请检查命令')

        # 下载数据集
        elif dataset_name is not None and model_name is None:
            try:
                sql = """
                    select dataset_path from app_dataset 
                    where user_id = '{}' and dataset_name='{}'
                """.format(user_id,dataset_name)
                result = dbutil.query(sql)
                if result:
                    dataset_path = result[0][0]
                    dataset_path = os.path.join(dataset_path, "")
                    zip_file_path = Utils.zip_dir(dataset_path)
                    file_name = os.path.basename(zip_file_path)
                    f = open(zip_file_path, 'rb')
                    response = FileResponse(f)  # 文件流类型
                    response['Content-Disposition'] = 'attachment; filename={}'.format(file_name)  # 表示带有文件附件，指定了文件名；浏览器会自动下载
                    return response
                else:
                    response = {
                        'msg':'数据集{}不存在'.format(dataset_name),
                        'status':404
                    }
                    return HttpResponse(json.dumps(response))
            except:
                response = {
                    'msg': '程序执行出错',
                    'status': 500
                }
                return HttpResponse(json.dumps(response))

        # 下载模型
        elif dataset_name is None and model_name is not None:
            try:
                sql = """
                    select model_path,status from app_model 
                    where user_id='{}' and model_name='{}'
                """.format(user_id, model_name)
                # print(sql)

                result = dbutil.query(sql)
                print(result)
                if result:
                    result = result[0]
                    if result[1] != 'finish':
                        response = {
                            'msg': "下载错误，模型未训练或训练未完成",
                            'status': 403
                        }
                        return HttpResponse(json.dumps(response,ensure_ascii=False))
                    else:
                        model_path = result[0]
                        file_name = model_name+'.pt'
                        model_file_path = os.path.join(model_path, file_name)
                        f = open(model_file_path, 'rb')
                        response = FileResponse(f)  # 文件流类型
                        response['Content-Disposition'] = 'attachment; filename={}'.format(
                            model_name + '.pt')  # 表示带有文件附件，指定了文件名；浏览器会自动下载
                        return response
                else:
                    response = {
                        'msg':"模型{}不存在".format(model_name),
                        'status':404
                    }
                    return HttpResponse(json.dumps(response,ensure_ascii=False))
            except:
                response = {
                    'msg': "程序执行出错",
                    'status': 500
                }
                return HttpResponse(json.dumps(response,ensure_ascii=False))


class Inference(View):
    def post(self, request, *args, **kwargs):
        """
        使用模型
        :param request:
        :return:
        """
        user_id = request.POST.get('user_id')
        model_name = request.POST.get('model_name')
        query = request.POST.get('query')
        src = request.POST.get('src')

        # 调用微服务
        nameko_config = NamekoConfig.nameko_config
        with ClusterRpcProxy(nameko_config) as cluster_rpc:
            response = cluster_rpc.ext_summary.get_summary(user_id, model_name,query,src)
        response = json.loads(response)

        return HttpResponse(json.dumps(response))


class Test(View):
    def get(self, request, *args, **kwargs):
        user_id = request.GET.get('user_id')
        model_name = request.GET.get('model_name')
        dataset_name = request.GET.get('dataset_name')

        response = {
            "msg": "开始测试模型demo_mode...",
            "status": 200
        }

        return HttpResponse(json.dumps(response))
class Test1(View):
    def get(self, request, *args, **kwargs):
        user_id = request.GET.get('user_id')
        model_name = request.GET.get('model_name')

        response = {
            "ROUGE-1": 35.09,
            "ROUGE-2": 19.47,
            "ROUGE-L": 34.51,
            "status": 200
        }

        return HttpResponse(json.dumps(response))
